package com.may.bio;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;

/**
 * @program: com.may.netty
 * @description: bio模式下。使用线程处理多客户端请求
 * @author: Bobby.Ma
 * @create: 2020-08-02 09:21
 * <p>
 * BIO的缺陷：
 * 1.每个客户端连接都需要创建线程，进行读/写，业务处理；
 * 2.并发大时需要创建大量线程，系统资源占用大；
 * 3.连接建立后，如果客户端没有请求数据，则线程会阻塞在 read 操作上，造成线程资源浪费。
 **/
public class BIOServer {
    /**
     * logger
     */
    private static final Logger log = LoggerFactory.getLogger(BIOServer.class);

    public static void main(String[] args) throws IOException {
        ExecutorService pool = Executors.newCachedThreadPool();
        ServerSocket serverSocket = new ServerSocket(8888);
        log.info("服务端启动了...");
        while (true) {
            log.info("服务端阻塞，并监听【8888】端口，等待客户端连接...");
            Socket socket = serverSocket.accept();
            log.info("服务端连接到一个客户端，开启线程处理与客户端的通讯！");
            pool.execute(() -> handler.accept(socket));
        }
    }

    private static final Consumer<Socket> handler = socket -> {
        try {
            log.info("【线程内部开始】：服务端阻塞，并等待客户端发送数据...");
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            int read;
            while ((read = inputStream.read(bytes)) != -1) {
                log.info("【线程内部】：服务端读取到客户端发送的数据：{}", new String(bytes, 0, read));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            log.info("【线程内部结束】：关闭与客户端的连接!");
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
}
